package com.nami.gchat.app.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.google.protobuf.ByteString;
import com.nami.gate.external.basic.bo.ConnectedUserBO;
import com.nami.gate.external.basic.cache.user.UserDeviceRel;
import com.nami.gate.external.basic.event.EventPublisher;
import com.nami.gate.external.basic.event.enums.EventType;
import com.nami.gate.external.basic.event.factory.EventFactory;
import com.nami.gate.external.basic.event.model.CommonEvent;
import com.nami.gchat.domain.gateway.UserGateway;
import com.nami.gchat.domain.model.co.GrpInfoModel;
import com.nami.gchat.domain.model.co.GrpMemberModel;
import com.nami.gchat.domain.repository.GroupRepository;
import com.nami.gchat.domain.repository.GrpMemberRepository;
import com.nami.gchat.domain.service.GrpChatDomainService;
import com.nami.gchat.facade.chat.GrpChatFacade;
import com.nami.gchat.facade.chat.request.GrpChatCmd;
import com.nami.im.network.model.enums.DownMsgErrorCode;
import com.nami.im.network.model.message.v2.Message;
import com.nami.transport.proto.codec.MqTransMsg;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.json.utils.JsonUtils;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 群聊
 *
 * @date 2025-02-18
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GrpChatFacadeImpl implements GrpChatFacade {

    private final UserGateway userGateway;
    private final GroupRepository groupRepository;
    private final GrpMemberRepository grpMemberRepository;
    private final GrpChatDomainService grpChatDomainService;
    private final EventPublisher eventPublisher;

    @Override
    public void execute(GrpChatCmd cmd) {
        TimeInterval timer = DateUtil.timer();
        Message message = cmd.getMessage();
        ConnectedUserBO sender = cmd.getSender();

        if (grpChatDomainService.validateBasicParams(sender, message, cmd.getTargetId())) {
            eventPublisher.publish(assembleDispatcherEvent(sender, message,
                DownMsgErrorCode.REQUEST_PARAMS_ERROR));
            return;
        }
        // 幂等校验
        if (grpChatDomainService.checkIdempotent(sender.getAppKey(),
            sender.getUserId(), message.getClientUid())) {
            log.warn("[c2g] 已丢弃客户端【{}】 clientMsgId={}的重复消息：{}",
                sender.getUserId(), message.getClientUid(),
                message.getMsgContent());
            return;
        }

        UserDeviceRel user = userGateway.getUserById(sender.getAppKey(),
            sender.getUserId());
        if (grpChatDomainService.validateUserPermission(user)) {
            return;
        }
        GrpInfoModel grpInfo = groupRepository.getGrpInfoFromCacheOrDB(sender.getAppKey(),
            cmd.getTargetId());
        if (grpChatDomainService.validateGrpParams(grpInfo)) {
            return;
        }
        List<GrpMemberModel> allMembers = grpMemberRepository
            .getGrpMembersFromCacheOrDB(cmd.getTargetId());
        if (CollUtil.isEmpty(allMembers)) {
            return;
        } // end group members null check

        GrpMemberModel me = allMembers.stream()
            .filter(item -> sender.getUserId().equals(item.getUserId()))
            .findFirst().orElse(null);
        if (grpChatDomainService.validateMePermission(me)) {
            return;
        }

        grpChatDomainService.fillParam(sender.getAppKey(), message);

        log.info("[c2g] 群号【{}】收到客户端【{}】发来的一条群消息. " +
                "clientMsgId==>{}，messageId==>{} 消息内容 ：{}",
            cmd.getTargetId(), sender.getUserIp(), message.getClientUid(),
            message.getMsgId(), message.getMsgContent());

        grpChatDomainService.publishMessageEvent(cmd.getQos(), sender,
            message, allMembers);
        log.info("[c2g] 用户【{}】向群【{}】发送的消息[clientUid={}, msgId={}]已处理完毕, use:{}ms",
            user.getNick(), cmd.getTargetId(),
            message.getClientUid(), message.getMsgId(), timer.interval());
    }

    private CommonEvent assembleDispatcherEvent(ConnectedUserBO sender,
                                                Message message,
                                                DownMsgErrorCode downMsgErrorCode) {

        MqTransMsg.TransUser senderUser = MqTransMsg.TransUser.newBuilder()
            .setAppKey(sender.getAppKey())
            .setUserId(sender.getUserId())
            .setPlatform(sender.getPlatform())
            .setConnectId(sender.getConnectId())
            .setInstanceId(sender.getInstanceId())
            .build();

        MqTransMsg.GrpLogic2DispatchBody logic2DispatchBody = MqTransMsg.GrpLogic2DispatchBody.newBuilder()
            .setSender(senderUser)
            .setMessage(ByteString.copyFromUtf8(JsonUtils.toJsonString(message)))
            .setSuccess(Boolean.FALSE)
            .setErrCode(downMsgErrorCode.getCode())
            .setErrMessage(downMsgErrorCode.getMsg())
            .build();
        return EventFactory.newEvent(EventType.SEND_DISPATCHER, logic2DispatchBody);
    }

}
